/*
 * Smtp.java
 *
 * Created on May 18, 2011
 */

package Clients;

import java.io.*;
import java.net.*;
import java.util.*;
import java.lang.Thread;
import java.net.URL;
import java.util.Properties;
import javax.activation.*;
import javax.mail.*;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.Authenticator;

import Clients.*;
import ProtoSimulator.*;

import org.apache.log4j.Logger;

/**
 *
 * @author  jjmb@jjmb.com
 */

public class Smtp extends Client {
    private static final String CLASS_NAME = Smtp.class.getName();
    private static int maxRequests = 0;
    private static String smtpBody = null;
    private static String smtpHost = "localhost";
    private static String smtpSubject = "["+CLASS_NAME+"]";
    private static Properties propertiesFile = null;
    private Status status;
    private Notification notification;
    private static String smtpResponse = null;
    private static String smtpTo = null;
    private static String smtpUser = null;
    private static String smtpPassword = null;
    private static String smtpPort = null;
    private static int iSmtpPort = 587; 
    private static long requestedElapsedTime = 0;
    private static long iterationElapsedTime = 0;
    private static boolean complete = false;

    public static Logger logger = Logger.getLogger(CLASS_NAME);
    
    public Smtp (Status s, Properties smtpProperties, int requests, Notification n) {
    	status = s;
    	propertiesFile = smtpProperties;
        maxRequests = requests;
        notification = n;
        
        smtpHost = propertiesFile.getProperty("mail.smtp.host");
        smtpBody = propertiesFile.getProperty("smtp_body");
        smtpSubject = propertiesFile.getProperty("smtp_subject") + ":" + this.getName() + ":" + this.getId();
        smtpTo = propertiesFile.getProperty("smtp_to");
        smtpUser = propertiesFile.getProperty("mail.smtp.user");
        smtpPassword = propertiesFile.getProperty("mail.smtp.password");
        
        // "Request("+ this.getName()  +"/"+this.getId()+") #" + requestCount + " processed, took " + requestedElapsedTime +"ms"
    }

	public void run() {
        int requestCount = 0;
        long i0 = System.currentTimeMillis();
                
    	Authenticator auth = new SmtpAuthenticator(smtpUser, smtpPassword);
        Session session = Session.getInstance(propertiesFile, auth);
        // session.setDebug(true);
        
        logger.trace("Session properties = " + session.getProperties().toString());  
        logger.trace("SMTP properties = " + propertiesFile.toString());        
        
        while(requestCount != maxRequests) {
            long r0 = System.currentTimeMillis();
            
            try { 
    			Message message = new MimeMessage(session);
    			MimeBodyPart messageBp = new MimeBodyPart();
    			MimeMultipart messageMp = new MimeMultipart();
    			
    			// setting from
    			message.setFrom(new InternetAddress(smtpUser));
    			// message.addFrom(new InternetAddress[] { new InternetAddress(smtpUser)});
    			// message.addRecipients(Message.RecipientType.TO, InternetAddress.parse(smtpTo));
    			
    			// setting to
    			message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(smtpTo, false));
    			
    			// setting subject
    			message.setSubject(smtpSubject);
    			smtpBody.concat("Thread ("+this.getName()+"/"+this.getId()+") sent this message.");
    			
    			// setting attachment
    			if(propertiesFile.getProperty("smtp_attachment") != null) {
    				messageBp.setText(smtpBody);
    				messageBp.attachFile(propertiesFile.getProperty("smtp_attachment"));
    				messageMp.addBodyPart(messageBp);
    				message.setContent(messageMp);
    			} else {
    				// setting body/text
        			message.setText(smtpBody);
    			}
    			
    			// setting header
    		    message.setHeader("X-Mailer", "JJMB");
    			
    			// setting sent date
    			message.setSentDate(new Date());
    			
    			logger.trace("Message subject = " + message.getSubject().toString());
    			
    			Transport transport = session.getTransport("smtp");
    			transport.connect(smtpHost, smtpUser, smtpPassword);
    			// transport.connect();
    			
    			// saving changes
    			message.saveChanges();    			
    			
    			// logger.debug("Sending mail using SMTP server, " + transport.getURLName());
    			
    			transport.send(message);
    			transport.close();
    			
    			/**
    			if(!transport.isConnected()) {
    				logger.fatal("Not connected to SMTP server");
    			} else {
    				logger.debug("Connected to SMTP server");
        			transport.send(message);
        			transport.close();
    			}
    			**/
            }
            catch(Exception e){
            	logger.fatal("Exception thrown sending SMTP message to " + smtpTo + ", from " + smtpUser + " with exception " + e);
                notification.setNotification(e.toString());
            }
            long r1 = System.currentTimeMillis();
            requestedElapsedTime = r1 - r0;
            logger.debug("Message("+ this.getName()  +"/"+this.getId()+") #" + requestCount + " processed, took " + requestedElapsedTime +"ms");
            requestCount++;
        }
        long i1 = System.currentTimeMillis();
        iterationElapsedTime = i1 - i0;
        logger.trace("Iteration elapsed time is " + iterationElapsedTime + "ms for thread ID " + this.getId());
        // status.setIterationElapsedTime(this.getId(), iterationElapsedTime);
        status.incrementIterationsComplete();
        logger.info("Iteration for message to " + smtpTo + ", (" + this.getName()  +"/"+this.getId()+") took " + iterationElapsedTime +"ms");
        
        try {
        	logger.debug("Joining thread("+this.getId()+")");
            this.join(100);
        }
        catch (Exception e) {
        	logger.fatal(e);
            notification.setNotification(e.toString());
        }
        // TODO move status processing here if it improves performance
	}
}